# -*- coding: utf-8 -*-

"""
@author: Laowang
@contact: QQ:1125564921
@Created on: 2022/6/20
@Remark: 
"""

from abc import ABC, abstractmethod
from typing import Any, List

from framework_strategy.gopy.main.engine import EventEngine, Event
from framework_strategy.gopy.trader.object import LogData, BaseData, _event
from framework_strategy.gopy.gateways.object import *
from .constant import *


class BaseAPI(ABC):
    """
    Abstract gateway class for creating gateways connection
    to different trading systems.

    # How to implement a gateway:
    ---
    ## Basics
    A gateway should satisfies:
    * this class should be thread-safe:
        * all methods should be thread-safe
        * no mutable shared properties between objects.
    * all methods should be non-blocked
    * satisfies all requirements written in docstring for every method and callbacks.
    * automatically reconnect if connection lost.

    ---

     Used for API authentication support
        ---
        # Methods supported after authentication
        * send_order
        * cancel_order
        * get_order_trade
        * get_open_order
        * get_account
        * send_orders
        * cancel_orders
    ---
    All the XxxData passed to callback should be constant, which means that
        the object should not be modified after passing to on_xxxx.
    So if you use a cache to store reference of data, use copy.copy to create a new object
    before passing that data into on_xxxx

    """

    # Exchanges supported in the gateway.
    exchanges: List[Exchange] = []

    def __init__(self, event_engine: EventEngine, api_name: str) -> None:
        self.event_engine: EventEngine = event_engine
        self.api_name: str = api_name

    def on_event(self, event_type: str, data: Any):
        """ Subscribe to the event """
        event = Event(event_type, data)
        self.event_engine.put(event)

    def get_server_time(self, data: ServerTimeData):
        self.on_event(*_event(EX_EVENT_SERVERTIMES, data))

    def get_order(self, data: BaseData):
        """ Example Query the order status """
        self.on_event(*_event(EX_EVENT_ORDER_STATUS, data))

    def get_orders(self, data: BaseData):
        """ Example Query the order status """
        self.on_event(*_event(EX_EVENT_ORDERS_STATUS, data))

    def get_trades(self, data: BaseData):
        """ Example Query historical transaction records """
        self.on_event(*_event(EX_EVENT_ORDER_TRADE, data))

    def get_ticker(self, data: BaseData):
        """ Example Query the ticker information of the market  """
        self.on_event(*_event(EX_EVENT_TICKER, data))

    def get_tickers(self, data: BaseData):
        """ All aggregate market """
        self.on_event(*_event(EX_EVENT_TICKERS, data))

    def get_klines(self, data: BaseData):
        """ Example Query the kline information of the market  """
        self.on_event(*_event(EX_EVENT_KLINE, data))

    def get_all_market_config(self, data: BaseData):
        """ Example Query the market information of the market  """
        self.on_event(*_event(EX_EVENT_MARKETCONFIG, data))

    def get_depth(self, data: BaseData):
        """ Example Query the depth information of the market  """
        self.on_event(*_event(EX_EVENT_MARKETDEPTH, data))

    def get_open_order(self, data: BaseData):
        """ Example Query the outstanding orders information of the market  """
        self.on_event(*_event(EX_EVENT_OPENORDER, data))

    def get_account(self, data: BaseData):
        """ Example Query the account information of the market  """
        self.on_event(*_event(EX_EVENT_ACCOUNT, data))

    def get_balance(self, data: BaseData):
        """ Get account balance  """
        self.on_event(*_event(EX_EVENT_ACCOUNT_BALANCE, data))

    def get_fund(self, data: BaseData):
        """ Gets the corresponding information for an account  """
        self.on_event(*_event(EX_EVENT_ACCOUNT_FUND, data))

    def send_order(self, data: BaseData):
        """ Order """
        self.on_event(*_event(EX_EVENT_SENDORDER, data))

    def send_orders(self, data: BaseData):
        """ Example batch orders  the market  """
        self.on_event(*_event(EX_EVENT_SENDORDERS, data))

    def cancel_order(self, data: BaseData):
        """ Example batch cancel orders  the market  """
        self.on_event(*_event(EX_EVENT_CANCELORDER, data))

    def cancel_orders(self, data: BaseData):
        """ Example batch cancel orders  the market  """
        self.on_event(*_event(EX_EVENT_CANCELORDERS, data))

    def get_mine_trades(self, data: BaseData):
        """ Example get mine orders  all market  """
        self.on_event(*_event(EX_EVENT_ACCOUNT_MINE_TRADES, data))

    def on_log(self, log: LogData):
        """ Log event push  """
        self.on_event(EVENT_LOG, log)

    def write_log(self, msg: str):
        """
        Write a log event from gateway.
        """
        log = LogData(msg=msg, source=self.api_name)
        self.on_log(log)


class API(BaseAPI):

    def __init__(self, event_engine: EventEngine) -> None:
        api_name: str = "API"
        super().__init__(event_engine, api_name)
